package com.bsj.sipgateway.sip.transmit.request.impl;


import com.bsj.sipgateway.cache.DeviceCache;
import com.bsj.sipgateway.config.SipConfig;
import com.bsj.sipgateway.sip.bean.Command;
import com.bsj.power.common.def.entity.gb28181.Device;
import com.bsj.sipgateway.sip.session.CallIdManager;
import com.bsj.sipgateway.sip.session.CommandManager;
import com.bsj.sipgateway.sip.transmit.request.SIPRequestAbstractProcessor;
import com.bsj.sipgateway.util.MediaPortUtils;
import gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.SipUri;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.sdp.Media;
import javax.sdp.MediaDescription;
import javax.sdp.SdpFactory;
import javax.sdp.SessionDescription;
import javax.sip.RequestEvent;
import javax.sip.header.CallIdHeader;
import javax.sip.header.FromHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.util.Vector;

/**
 * @Description:处理INVITE请求
 * @author bsj-chenjunkang
 * @date 2022/8/24
 */
@Slf4j
public class InviteRequestProcessor extends SIPRequestAbstractProcessor {

    private SipConfig sipConfig;

    private MediaPortUtils mediaPortUtils;

    /**
     * 处理invite请求
     *
     * @param evt 请求消息
     */
    @Override
    public void process(RequestEvent evt) {
        //开始处理语音广播的invite请求
        try {
            //获取设备id
            Request request = evt.getRequest();
            CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
            FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
            AddressImpl address = (AddressImpl) fromHeader.getAddress();
            SipUri uri = (SipUri) address.getURI();
            String deviceId = uri.getUser();
            if (StringUtils.isBlank(deviceId)) {
                log.info("处理语音广播的invite请求时无法获取设备id");
                // 参数不全， 发400，请求错误
                responseAck(evt, Response.BAD_REQUEST);
                return;
            }
            Device device = DeviceCache.getDevice(deviceId);
            if(device==null){
                log.info("处理语音广播的invite请求时无法设备信息，设备不在线");
                // 参数不全， 发400，请求错误
                responseAck(evt, Response.BAD_REQUEST);
                return;
            }
            Long did = device.getId();
            //判断是否有语音广播的命令缓存，如果有则回复200OK，并且刷新缓存过期时间
            Command commandCache = CommandManager.getWithBroadcast(deviceId);
            if (commandCache != null) {
                //解析sdp内容
                // jainSip不支持y=字段， 移除移除以解析
                String contentString = new String(request.getRawContent());
                String substring = contentString;
                String ssrc = "";
                int ssrcIndex = contentString.indexOf("y=");
                if (ssrcIndex > 0) {
                    substring = contentString.substring(0, ssrcIndex);
                    ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim();
                }
                ssrcIndex = substring.indexOf("f=");
                if (ssrcIndex > 0) {
                    substring = contentString.substring(0, ssrcIndex);
                }
                SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
                //获取设备的ip 端口
                Vector mediaDescriptions = sdp.getMediaDescriptions(true);
                // 查看是否支持PS 负载96
                int devicePort = -1;
                for (int i = 0; i < mediaDescriptions.size(); i++) {
                    MediaDescription mediaDescription = (MediaDescription) mediaDescriptions.get(i);
                    Media media = mediaDescription.getMedia();
                    Vector mediaFormats = media.getMediaFormats(false);
                    if (mediaFormats.contains("8")) {
                        devicePort = media.getMediaPort();
                        break;
                    }
                }
                if (devicePort == -1) {
                    // 回复不支持的格式
                    responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式，发415
                    return;
                }
                //username也是设备id，无用暂留
                String username = sdp.getOrigin().getUsername();
                String deviceIp = sdp.getOrigin().getAddress();
                boolean isTcpWay = false;
                String mediaPort = sipConfig.getMediaTcpPort()+" ";
                if (isTcpWay){
                    mediaPort = sipConfig.getMediaUdpPort()+" TCP/";
                }
                //存缓存
                CallIdManager.put(callIdHeader.getCallId(), deviceId, deviceIp, devicePort, ssrc);
                //响应内容
                StringBuffer content = new StringBuffer(200);
                content.append("v=0\r\n");
                content.append("o="+ sipConfig.getSipDomain() +" 0 0 IN IP4 "+sipConfig.getSipRealIp()+"\r\n");
                content.append("s=Play\r\n");
                content.append("c=IN IP4 "+sipConfig.getSipRealIp()+"\r\n");
                content.append("t=0 0\r\n");
                content.append("m=audio "+ mediaPort +"RTP/AVP 96\r\n");
                content.append("a=sendonly\r\n");
                content.append("a=rtpmap:96 PS/90000\r\n");
                content.append("y="+ ssrc + "\r\n");
                content.append("f=\r\n");
                //回复 200 OK
                responseSdpAck(evt, content.toString());

            } else {
                //没有说明命令已过期
                log.info("处理语音广播的invite请求时设备{}没有找到mq命令", deviceId);
                responseAck(evt, Response.BAD_REQUEST);
            }
        } catch (Exception e) {
            log.error("处理语音广播的invite请求异常", e);
        }
    }

    public void setSipConfig(SipConfig sipConfig) {
        this.sipConfig = sipConfig;
    }

    public void setMediaPortUtils(MediaPortUtils mediaPortUtils) {
        this.mediaPortUtils = mediaPortUtils;
    }
}
